package com.fsnbigdata.aspect;

import com.fsnbigdata.domain.Log;
import com.fsnbigdata.security.auth.TokenHelper;
import com.fsnbigdata.service.api.LogService;
import com.fsnbigdata.util.IPTOAddress;
import io.swagger.annotations.ApiOperation;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by zq on 2019/3/21.
 */
@Aspect // 标记为切面
@Component
public class LoggerAspect {

    @Autowired
    private  LogService logService;

    @Autowired
    private TokenHelper tokenHelper;

    private  static LoggerAspect loggerAspect ;


    //初始化静态参数
    @PostConstruct
    public void init() {
        loggerAspect = this;
        loggerAspect.logService = this.logService;
        loggerAspect.tokenHelper= this.tokenHelper;
    }


     @Pointcut("@annotation(io.swagger.annotations.ApiOperation)")
//     @Pointcut("execution(public * com.fsnbigdata.web.*.*(..))")
    public void controllerAspect() {

    }

    /**
     * 在目标方法正常完成后拦截记录Controller层用户的操作
     * @param joinPoint
     * 切点
     */
    @AfterReturning("controllerAspect()")
    public void doBefore(JoinPoint joinPoint) throws Exception {
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest httpServletRequest = servletRequestAttributes.getRequest();

        String authToken =loggerAspect.tokenHelper.getToken(httpServletRequest);

        if (authToken!=null){
            Log log = new Log();
            //获取用户名
            String username = loggerAspect.tokenHelper.getUsernameFromToken(authToken);
            List<String> list =  getControllerMethodDescription(joinPoint);
            if (list.size()>0){
                log.setDescription(list.get(0));
                log.setType(list.get(1));
                log.setUsername(username);
                log.setCreateTime(new Date());
                log.setGenre("0");
                log.setAddress(IPTOAddress.addr(IPTOAddress.getIP(httpServletRequest)));
                log.setClientInformation(IPTOAddress.getAddr(httpServletRequest));
                log.setIp(IPTOAddress.getIP(httpServletRequest));
                //保存日志
                loggerAspect.logService.save(log);
            }

        }
    }

    /**
     *
     */
    public static List<String> getControllerMethodDescription(JoinPoint joinPoint) throws Exception {

        List<String> list = new ArrayList<>();

        if (joinPoint.getTarget()!=null){
            // 类名
            String targetName = joinPoint.getTarget().getClass().getName();
            // 方法名
            String methodName = joinPoint.getSignature().getName();
            // 参数
            Object[] arguments = joinPoint.getArgs();
            // 切点类
            Class targetClass = Class.forName(targetName);

            Method[] methods = targetClass.getMethods();

            for (Method method : methods) {
                if (method.getName().equals(methodName)) {
                    Class[] clazzs = method.getParameterTypes();
                    if (clazzs.length == arguments.length) {

                        if (method.getAnnotation(ApiOperation.class)!=null){
                            // 获取描述
                            list.add(method.getAnnotation(ApiOperation.class).value());
                            //获取类型
                            list.add(method.getAnnotation(ApiOperation.class).notes());
                        }
                        break;
                    }
                }
            }
        }

       return list;
   }


}
